home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************\
- * Copyright (c) 1991 by Wen-King Su (wen-king@vlsi.cs.caltech.edu) *
- * *
- * You may copy or modify this file in any manner you wish, provided *
- * that this notice is always included, and that you hold the author *
- * harmless for any loss or damage resulting from the installation or *
- * use of this software. *
- \*********************************************************************/
-
- #include "tweak.h"
- #include "client_def.h"
- #include "c_extern.h"
- #include "co_extern.h"
-
- extern int errno;
-
- static int myfd;
- static struct sockaddr_in server_addr;
- static unsigned short myseq = 0;
- static unsigned short key;
-
- int client_trace = 0;
- int client_intr_state = 0;
- unsigned long target_delay = MIN_DELAY; /* expected max delay */
- unsigned long busy_delay = MIN_DELAY; /* busy retransmit timer */
- unsigned long idle_delay = MIN_DELAY; /* idle retransmit timer */
- unsigned long udp_sent_time;
-
- UBUF *client_interact PROTO6(unsigned int, cmd, unsigned long, pos,
- unsigned int, l1, unsigned char *, p1,
- unsigned int, l2, unsigned char *, p2)
- {
- struct sockaddr_in from;
- UBUF sbuf;
- static UBUF rbuf;
- unsigned char *s, *t, *d, seq0, seq1;
- unsigned u, n, sum, mask, mlen, rlen;
- int retval, bytes, retry_send, retry_recv;
- unsigned long w_delay;
-
- sbuf.cmd = cmd;
- BB_WRITE2(sbuf.bb_len,l1);
- BB_WRITE4(sbuf.bb_pos,pos);
-
- client_intr_state = 1;
-
- for(u = l1, d = (unsigned char *) sbuf.buf; u--; *d++ = *p1++);
- for(u = l2; u--; *d++ = *p2++);
- mlen = d - (unsigned char *) &sbuf;
-
- key = client_get_key();
-
- for(retry_send = 0; ; retry_send++) {
- BB_WRITE2(sbuf.bb_key,key);
- sbuf.bb_seq[0] = seq0 = (myseq >> 8) & 0xff;
- sbuf.bb_seq[1] = seq1 = (myseq & 0xfc) | (retry_send & 0x0003);
- sbuf.sum = 0;
-
- for(t = (unsigned char *) &sbuf, sum = n = mlen; n--; sum += *t++);
- sbuf.sum = sum + (sum >> 8);
-
- switch(retry_send) { /* adaptive retry delay adjustments */
- case 0:
- busy_delay = (target_delay+(busy_delay<<3)-busy_delay)>>3;
- w_delay = busy_delay;
- break;
- case 1:
- busy_delay = busy_delay + (busy_delay >> 1);
- w_delay = busy_delay;
- if(client_trace) write(2,"R",1); break;
-
- default:
- #ifdef CLIENT_TIMEOUT
- if (!pos && retry_send >= env_timeout ) {
- fprintf(stderr, "\rRemote server not responding.\n");
- exit(1);
- }
- #endif
- if(idle_delay < 5*60*1000) idle_delay = idle_delay << 1;
- w_delay = idle_delay;
- if(client_trace) write(2,"I",1);
- break;
- }
-
- if(sendto(myfd,&sbuf,mlen,0,(struct sockaddr *)&server_addr,
- sizeof(server_addr)) == -1) {
- perror("sendto");
- exit(1);
- }
- udp_sent_time = time((time_t *) 0);
- mask = 1 << myfd;
-
- for(retry_recv = 0; ; retry_recv++) {
- if(retry_recv && client_trace) write(2,"E",1);
- retval = _x_select(&mask, w_delay);
- if((retval == -1) && (errno == EINTR)) continue;
- if(retval == 1) { /* an incoming message is waiting */
- bytes = sizeof(from);
- if((bytes = recvfrom(myfd,(char*)&rbuf,sizeof(rbuf),0,
- (struct sockaddr *)&from, &bytes)) < UBUF_HSIZE)
- continue;
-
- s = (unsigned char *) &rbuf;
- d = s + bytes;
- u = rbuf.sum; rbuf.sum = 0;
- for(t = s, sum = 0; t < d; sum += *t++);
- sum = (sum + (sum >> 8)) & 0xff;
- if(sum != u) continue; /* wrong check sum */
-
- rlen = BB_READ2(rbuf.bb_len);
-
- if( (rbuf.bb_seq[0] ^ seq0) ||
- ((rbuf.bb_seq[1] ^ seq1)&0xfc)) continue; /* wrong seq # */
- if((int) (rlen+UBUF_HSIZE) > bytes) continue; /* truncated. */
-
- myseq = (myseq + 0x0004) & 0xfffc; /* seq for next request */
- key = BB_READ2(rbuf.bb_key); /* key for next request */
-
- client_put_key(key);
-
- if(client_intr_state == 2) {
- if(!key_persists) client_done();
- exit(1);
- }
-
- return(&rbuf);
-
- } else break; /* go back to re-transmit buffer again */
- }
- }
- }
-
- void init_client PROTO3(char *, host, int, port, int, myport)
- {
- busy_delay = idle_delay = target_delay;
-
- if((myfd = _x_udp(&myport)) == -1) {
- perror("socket open");
- exit(1);
- }
-
- if(_x_adr(host,port,&server_addr) == -1) {
- perror("server addr");
- exit(1);
- }
-
- client_init_key(server_addr.sin_addr.s_addr,port,getpid());
- }
-
- int client_done PROTO0((void))
- {
- (void) client_interact(CC_BYE, 0L, 0, (unsigned char *)NULLP, 0,
- (unsigned char *)NULLP);
- }
-